home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch17 / Cylinder.cls < prev    next >
Text File  |  1999-07-06  |  18KB  |  579 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "RayCylinder"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = False
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' A cylinder object.
  17.  
  18. Implements RayTraceable
  19.  
  20. ' Geometry.
  21. Private Point2 As Point3D
  22. Private Point1 As Point3D
  23. Private Radius As Single
  24.  
  25. Private Const NUM_THETA = 10
  26. Private WireFrame(1 To NUM_THETA, 1 To 2) As Point3D
  27.  
  28. ' The value of u at the hit location.
  29. Private HitU As Single
  30.  
  31. ' Ambient light parameters.
  32. Private AmbientKr As Single
  33. Private AmbientKg As Single
  34. Private AmbientKb As Single
  35.  
  36. ' Diffuse light parameters.
  37. Private DiffuseKr As Single
  38. Private DiffuseKg As Single
  39. Private DiffuseKb As Single
  40.  
  41. ' Specular reflection parameters.
  42. Private SpecularN As Single
  43. Private SpecularK As Single
  44.  
  45. ' Reflected light parameters.
  46. Private ReflectedKr As Single
  47. Private ReflectedKg As Single
  48. Private ReflectedKb As Single
  49.  
  50. ' Refracted light parameters.
  51. Private TransN As Single
  52. Private n1 As Single   ' Index of refraction outside the object.
  53. Private n2 As Single   ' Index of refraction inside the object.
  54. Private TransmittedKr As Single
  55. Private TransmittedKg As Single
  56. Private TransmittedKb As Single
  57.  
  58. Private IsReflective As Boolean
  59. Private IsTransparent As Boolean
  60. Private DoneOnThisScanline As Boolean
  61.  
  62. ' We had a hit on this scanline.
  63. Private HadHit As Boolean
  64.  
  65. ' We have had a hit on a previous scanline.
  66. Private HadHitOnPreviousScanline As Boolean
  67.  
  68. ' We will not be visible on later scanlines.
  69. Private ForeverCulled As Boolean
  70. ' Return the right shade for this polygon.
  71. Private Function GetShade(ByVal pgon As SimplePolygon) As Long
  72. Dim i As Integer
  73. Dim px As Single
  74. Dim py As Single
  75. Dim pz As Single
  76. Dim light_source As LightSource
  77. Dim total_r As Single
  78. Dim total_g As Single
  79. Dim total_b As Single
  80. Dim R1 As Integer
  81. Dim g1 As Integer
  82. Dim b1 As Integer
  83. Dim empty_objects As Collection
  84.  
  85.     With pgon
  86.         ' Find a central point on this polygon.
  87.         For i = 1 To .PointX.Count
  88.             px = px + .PointX(i)
  89.             py = py + .PointY(i)
  90.             pz = pz + .PointZ(i)
  91.         Next i
  92.         px = px / .PointX.Count
  93.         py = py / .PointX.Count
  94.         pz = pz / .PointX.Count
  95.  
  96.         ' Add up the light components.
  97.         Set empty_objects = New Collection
  98.         For Each light_source In LightSources
  99.             CalculateHitColorDSA _
  100.                 1, empty_objects, Nothing, _
  101.                 EyeX, EyeY, EyeZ, _
  102.                 px, py, pz, .Nx, .Ny, .Nz, _
  103.                 DiffuseKr, DiffuseKg, DiffuseKb, AmbientKr, AmbientKg, AmbientKb, _
  104.                 SpecularK, SpecularN, R1, g1, b1
  105.             total_r = total_r + R1
  106.             total_g = total_g + g1
  107.             total_b = total_b + b1
  108.         Next light_source
  109.     End With
  110.  
  111.     If total_r > 255 Then total_r = 255
  112.     If total_g > 255 Then total_g = 255
  113.     If total_b > 255 Then total_b = 255
  114.  
  115.     GetShade = RGB(total_r, total_g, total_b)
  116. End Function
  117. ' Draw a face if it is not a backface.
  118. Private Sub DrawFace(ByVal pic As PictureBox, X() As Single, Y() As Single, Z() As Single)
  119. Dim pgon As SimplePolygon
  120. Dim i As Integer
  121.  
  122.     ' Make a polygon.
  123.     Set pgon = New SimplePolygon
  124.     For i = 1 To 4
  125.         pgon.AddPoint X(i), Y(i), Z(i)
  126.     Next i
  127.     pgon.Finish
  128.  
  129.     ' If it is not a backface, draw it.
  130.     If Not pgon.IsBackface() Then
  131.         pgon.ForeColor = GetColor()
  132.         pgon.DrawPolygon pic
  133.     End If
  134. End Sub
  135. ' Add non-backface polygons to this collection.
  136. Public Sub RayTraceable_GetPolygons(ByRef num_polygons As Integer, polygons() As SimplePolygon, ByVal shaded As Boolean)
  137. Dim t As Integer
  138. Dim last_t As Integer
  139. Dim pgon As SimplePolygon
  140. Dim i As Integer
  141. Dim color As Long
  142.  
  143.     ' If all polygons are the same color,
  144.     ' get an appropriate color.
  145.     If Not shaded Then
  146.         color = GetColor()
  147.     End If
  148.  
  149.     last_t = NUM_THETA
  150.     For t = 1 To NUM_THETA
  151.         ' Make a polygon.
  152.         Set pgon = New SimplePolygon
  153.         With WireFrame(last_t, 1)
  154.             pgon.AddPoint .Trans(1), .Trans(2), .Trans(3)
  155.         End With
  156.         With WireFrame(t, 1)
  157.             pgon.AddPoint .Trans(1), .Trans(2), .Trans(3)
  158.         End With
  159.         With WireFrame(t, 2)
  160.             pgon.AddPoint .Trans(1), .Trans(2), .Trans(3)
  161.         End With
  162.         With WireFrame(last_t, 2)
  163.             pgon.AddPoint .Trans(1), .Trans(2), .Trans(3)
  164.         End With
  165.         pgon.Finish
  166.  
  167.         ' See if this is a backface.
  168.         If Not pgon.IsBackface() Then
  169.             ' This is not a backface. Add it to
  170.             ' the list.
  171.             With pgon
  172.                 ' See if we are shaded.
  173.                 If shaded Then
  174.                     ' We are shaded. Get the
  175.                     ' right color.
  176.                     .ForeColor = GetShade(pgon)
  177.                     .FillColor = .ForeColor
  178.                 Else
  179.                     ' We are not shaded. Use the
  180.                     ' normal colors.
  181.                     .ForeColor = vbBlack
  182.                     .FillColor = color
  183.                 End If
  184.                 num_polygons = num_polygons + 1
  185.                 ReDim Preserve polygons(1 To num_polygons)
  186.                 Set polygons(num_polygons) = pgon
  187.             End With
  188.         End If
  189.         last_t = t
  190.     Next t
  191. End Sub
  192. ' Make a wire frame.
  193. Private Sub MakeWireFrame()
  194. Const PI = 3.14159265
  195.  
  196. Dim v1x As Single
  197. Dim v1y As Single
  198. Dim v1z As Single
  199. Dim v2x As Single
  200. Dim v2y As Single
  201. Dim v2z As Single
  202. Dim i As Integer
  203. Dim theta As Single
  204. Dim dtheta As Single
  205. Dim v1_scale As Single
  206. Dim v2_scale As Single
  207. Dim X As Single
  208. Dim Y As Single
  209. Dim Z As Single
  210.  
  211.     ' Get two vectors perpendicular to the axis.
  212.     GetLineNormals _
  213.         Point2.Coord(1) - Point1.Coord(1), _
  214.         Point2.Coord(2) - Point1.Coord(2), _
  215.         Point2.Coord(3) - Point1.Coord(3), _
  216.         v1x, v1y, v1z, v2x, v2y, v2z
  217.  
  218.     ' Generate the wire frame points.
  219.     theta = 0
  220.     dtheta = 2 * PI / NUM_THETA
  221.     For i = 1 To NUM_THETA
  222.         v1_scale = Sin(theta) * Radius
  223.         v2_scale = Cos(theta) * Radius
  224.         With WireFrame(i, 1)
  225.             .Coord(1) = Point1.Coord(1) + v2_scale * v1x + v1_scale * v2x
  226.             .Coord(2) = Point1.Coord(2) + v2_scale * v1y + v1_scale * v2y
  227.             .Coord(3) = Point1.Coord(3) + v2_scale * v1z + v1_scale * v2z
  228.             .Coord(4) = 1#
  229.         End With
  230.         With WireFrame(i, 2)
  231.             .Coord(1) = Point2.Coord(1) + v2_scale * v1x + v1_scale * v2x
  232.             .Coord(2) = Point2.Coord(2) + v2_scale * v1y + v1_scale * v2y
  233.             .Coord(3) = Point2.Coord(3) + v2_scale * v1z + v1_scale * v2z
  234.             .Coord(4) = 1#
  235.         End With
  236.         theta = theta + dtheta
  237.     Next i
  238. End Sub
  239.  
  240. ' Return an appropriate color for this object.
  241. Private Function GetColor() As Long
  242. Dim R As Integer
  243. Dim G As Integer
  244. Dim B As Integer
  245.  
  246.     R = 255 * (DiffuseKr + AmbientKr): If R > 255 Then R = 255
  247.     G = 255 * (DiffuseKg + AmbientKg): If G > 255 Then G = 255
  248.     B = 255 * (DiffuseKb + AmbientKb): If B > 255 Then B = 255
  249.     GetColor = RGB(R, G, B)
  250. End Function
  251.  
  252. ' Initialize the object using text parameters in
  253. ' a comma-delimited list.
  254. Public Sub SetParameters(ByVal txt As String)
  255.     On Error GoTo CylinderParamError
  256.  
  257.     ' Read the parameters and initialize the object.
  258.     ' Geometry.
  259.     Radius = CSng(GetDelimitedToken(txt, ","))
  260.     Point1.Coord(1) = CSng(GetDelimitedToken(txt, ","))
  261.     Point1.Coord(2) = CSng(GetDelimitedToken(txt, ","))
  262.     Point1.Coord(3) = CSng(GetDelimitedToken(txt, ","))
  263.     Point1.Coord(4) = 1
  264.     Point2.Coord(1) = CSng(GetDelimitedToken(txt, ","))
  265.     Point2.Coord(2) = CSng(GetDelimitedToken(txt, ","))
  266.     Point2.Coord(3) = CSng(GetDelimitedToken(txt, ","))
  267.     Point2.Coord(4) = 1
  268.  
  269.     ' Ambient light.
  270.     AmbientKr = CSng(GetDelimitedToken(txt, ","))
  271.     AmbientKg = CSng(GetDelimitedToken(txt, ","))
  272.     AmbientKb = CSng(GetDelimitedToken(txt, ","))
  273.  
  274.     ' Diffuse reflection.
  275.     DiffuseKr = CSng(GetDelimitedToken(txt, ","))
  276.     DiffuseKg = CSng(GetDelimitedToken(txt, ","))
  277.     DiffuseKb = CSng(GetDelimitedToken(txt, ","))
  278.  
  279.     ' Specular reflection.
  280.     SpecularN = CSng(GetDelimitedToken(txt, ","))
  281.     SpecularK = CSng(GetDelimitedToken(txt, ","))
  282.  
  283.     ' Reflected light.
  284.     ReflectedKr = CSng(GetDelimitedToken(txt, ","))
  285.     ReflectedKg = CSng(GetDelimitedToken(txt, ","))
  286.     ReflectedKb = CSng(GetDelimitedToken(txt, ","))
  287.     IsReflective = (ReflectedKr > 0) Or (ReflectedKg > 0) Or (ReflectedKb > 0)
  288.  
  289.     ' Transmitted light.
  290.     TransN = CSng(GetDelimitedToken(txt, ","))
  291.     n1 = CSng(GetDelimitedToken(txt, ","))
  292.     n2 = CSng(GetDelimitedToken(txt, ","))
  293.     TransmittedKr = CSng(GetDelimitedToken(txt, ","))
  294.     TransmittedKg = CSng(GetDelimitedToken(txt, ","))
  295.     TransmittedKb = CSng(GetDelimitedToken(txt, ","))
  296.     IsTransparent = (TransmittedKr > 0) Or (TransmittedKg > 0) Or (TransmittedKb > 0)
  297.  
  298.     ' Make a wire frame.
  299.     MakeWireFrame
  300.  
  301.     Exit Sub
  302.  
  303. CylinderParamError:
  304.     MsgBox "Error initializing cylinder parameters."
  305. End Sub
  306.  
  307. ' Draw a wireframe for this object.
  308. Public Sub RayTraceable_DrawWireFrame(ByVal pic As PictureBox)
  309. Dim t As Integer
  310. Dim last_t As Integer
  311.  
  312.     ' Use an appropriate color.
  313.     pic.ForeColor = GetColor()
  314.  
  315.     last_t = NUM_THETA
  316.     For t = 1 To NUM_THETA
  317.         pic.Line (WireFrame(last_t, 1).Trans(1), WireFrame(last_t, 1).Trans(2))- _
  318.             (WireFrame(t, 1).Trans(1), WireFrame(t, 1).Trans(2))
  319.         pic.Line -(WireFrame(t, 2).Trans(1), WireFrame(t, 2).Trans(2))
  320.         pic.Line -(WireFrame(last_t, 2).Trans(1), WireFrame(last_t, 2).Trans(2))
  321.         last_t = t
  322.     Next t
  323. End Sub
  324. ' Draw the object with backfaces removed.
  325. Public Sub RayTraceable_DrawBackfacesRemoved(ByVal pic As PictureBox)
  326. Dim t As Integer
  327. Dim last_t As Integer
  328. Dim X(1 To 4) As Single
  329. Dim Y(1 To 4) As Single
  330. Dim Z(1 To 4) As Single
  331.  
  332.     ' Use an appropriate color.
  333.     pic.ForeColor = GetColor()
  334.  
  335.     last_t = NUM_THETA
  336.     For t = 1 To NUM_THETA
  337.         With WireFrame(last_t, 1)
  338.             X(1) = .Trans(1)
  339.             Y(1) = .Trans(2)
  340.             Z(1) = .Trans(3)
  341.         End With
  342.         With WireFrame(t, 1)
  343.             X(2) = .Trans(1)
  344.             Y(2) = .Trans(2)
  345.             Z(2) = .Trans(3)
  346.         End With
  347.         With WireFrame(t, 2)
  348.             X(3) = .Trans(1)
  349.             Y(3) = .Trans(2)
  350.             Z(3) = .Trans(3)
  351.         End With
  352.         With WireFrame(last_t, 2)
  353.             X(4) = .Trans(1)
  354.             Y(4) = .Trans(2)
  355.             Z(4) = .Trans(3)
  356.         End With
  357.  
  358.         DrawFace pic, X, Y, Z
  359.         last_t = t
  360.     Next t
  361. End Sub
  362. ' Apply a transformation matrix to the object.
  363. Public Sub RayTraceable_Apply(M() As Single)
  364. Dim i_theta As Integer
  365.  
  366.     ' Transform the wire frame.
  367.     For i_theta = 1 To NUM_THETA
  368.         m3Apply WireFrame(i_theta, 1).Coord, _
  369.              M, WireFrame(i_theta, 1).Trans
  370.         m3Apply WireFrame(i_theta, 2).Coord, _
  371.              M, WireFrame(i_theta, 2).Trans
  372.     Next i_theta
  373.  
  374.     ' Transform the points.
  375.     m3Apply Point1.Coord, M, Point1.Trans
  376.     m3Apply Point2.Coord, M, Point2.Trans
  377. End Sub
  378. ' Apply a transformation matrix to the object.
  379. Public Sub RayTraceable_ApplyFull(M() As Single)
  380. Dim i_theta As Integer
  381.  
  382.     ' Transform the wire frame.
  383.     For i_theta = 1 To NUM_THETA
  384.         m3ApplyFull WireFrame(i_theta, 1).Coord, _
  385.                  M, WireFrame(i_theta, 1).Trans
  386.         m3ApplyFull WireFrame(i_theta, 2).Coord, _
  387.                  M, WireFrame(i_theta, 2).Trans
  388.     Next i_theta
  389.  
  390.     ' Transform the points.
  391.     m3ApplyFull Point1.Coord, M, Point1.Trans
  392.     m3ApplyFull Point2.Coord, M, Point2.Trans
  393. End Sub
  394.  
  395. ' Return the red, green, and blue components of
  396. ' the surface at the hit position.
  397. Public Sub RayTraceable_FindHitColor( _
  398.     ByVal depth As Integer, Objects As Collection, _
  399.     ByVal eye_x As Single, ByVal eye_y As Single, ByVal eye_z As Single, _
  400.     ByVal px As Single, ByVal py As Single, ByVal pz As Single, _
  401.     ByRef R As Integer, ByRef G As Integer, ByRef B As Integer)
  402. Dim Vx As Single
  403. Dim Vy As Single
  404. Dim Vz As Single
  405. Dim Nx As Single
  406. Dim Ny As Single
  407. Dim Nz As Single
  408. Dim n_len  As Single
  409.  
  410.     ' Find the unit normal at this point.
  411.     Vx = Point2.Trans(1) - Point1.Trans(1)
  412.     Vy = Point2.Trans(2) - Point1.Trans(2)
  413.     Vz = Point2.Trans(3) - Point1.Trans(3)
  414.     Nx = px - (Point1.Trans(1) + HitU * Vx)
  415.     Ny = py - (Point1.Trans(2) + HitU * Vy)
  416.     Nz = pz - (Point1.Trans(3) + HitU * Vz)
  417.     n_len = Sqr(Nx * Nx + Ny * Ny + Nz * Nz)
  418.     Nx = Nx / n_len
  419.     Ny = Ny / n_len
  420.     Nz = Nz / n_len
  421.  
  422.     ' Get the hit color.
  423.     CalculateHitColor depth, Objects, Me, _
  424.         eye_x, eye_y, eye_z, _
  425.         px, py, pz, _
  426.         Nx, Ny, Nz, _
  427.         DiffuseKr, DiffuseKg, DiffuseKb, _
  428.         AmbientKr, AmbientKg, AmbientKb, _
  429.         SpecularK, SpecularN, _
  430.         ReflectedKr, ReflectedKg, ReflectedKb, IsReflective, _
  431.         TransmittedKr, TransmittedKg, TransmittedKb, TransN, n1, n2, IsTransparent, _
  432.         R, G, B
  433. End Sub
  434. ' See if the scanline plane with the indicated
  435. ' point and normal intersects this object. Set
  436. ' the object's DoneOnThisScanline flag appropriately.
  437. Public Sub RayTraceable_CullScanline(ByVal px As Single, ByVal py As Single, ByVal pz As Single, ByVal Nx As Single, ByVal Ny As Single, ByVal Nz As Single)
  438.     ' See if we will ever be visible again.
  439.     If ForeverCulled Then
  440.         DoneOnThisScanline = True
  441.         Exit Sub
  442.     End If
  443.  
  444.     ' We have not yet had a hit on this scanline.
  445.     HadHit = False
  446.  
  447.     ' Do not scanline cull.
  448.     DoneOnThisScanline = False
  449. End Sub
  450. ' Return the value T for the point of intersection
  451. ' between the vector from point (px, py, pz) in
  452. ' the direction <wx, wy, wz>.
  453. '
  454. ' direct_calculation is true if we are finding the
  455. ' intersection from a viewing position ray. It is
  456. ' false if we are finding an reflected intersection
  457. ' or a shadow feeler.
  458. Public Function RayTraceable_FindT(ByVal direct_calculation As Boolean, ByVal px As Single, ByVal py As Single, ByVal pz As Single, ByVal Vx As Single, ByVal Vy As Single, ByVal Vz As Single) As Single
  459. Dim x1 As Single
  460. Dim y1 As Single
  461. Dim z1 As Single
  462. Dim Wx As Single
  463. Dim Wy As Single
  464. Dim Wz As Single
  465. Dim w_len_squared As Single
  466. Dim WdotV As Single
  467. Dim A As Single
  468. Dim B As Single
  469. Dim Cx As Single
  470. Dim Cy As Single
  471. Dim Cz As Single
  472. Dim dx As Single
  473. Dim dy As Single
  474. Dim dz As Single
  475. Dim A1 As Single
  476. Dim b1 As Single
  477. Dim C1 As Single
  478. Dim B24AC As Single
  479. Dim t1 As Single
  480. Dim t2 As Single
  481.  
  482.     ' Find the axis vector.
  483.     Wx = Point2.Trans(1) - Point1.Trans(1)
  484.     Wy = Point2.Trans(2) - Point1.Trans(2)
  485.     Wz = Point2.Trans(3) - Point1.Trans(3)
  486.     
  487.     ' Find A and B for u = A * t + B.
  488.     w_len_squared = Wx * Wx + Wy * Wy + Wz * Wz
  489.     WdotV = Wx * Vx + Wy * Vy + Wz * Vz
  490.     A = WdotV / w_len_squared
  491.  
  492.     x1 = Point1.Trans(1)
  493.     y1 = Point1.Trans(2)
  494.     z1 = Point1.Trans(3)
  495.     B = (Wx * (px - x1) + _
  496.          Wy * (py - y1) + _
  497.          Wz * (pz - z1)) / w_len_squared
  498.  
  499.     ' Solve for t.
  500.     Cx = Vx - Wx * A
  501.     Cy = Vy - Wy * A
  502.     Cz = Vz - Wz * A
  503.     dx = px - x1 - Wx * B
  504.     dy = py - y1 - Wy * B
  505.     dz = pz - z1 - Wz * B
  506.     A1 = Cx * Cx + Cy * Cy + Cz * Cz
  507.     b1 = 2 * (Cx * dx + Cy * dy + Cz * dz)
  508.     C1 = dx * dx + dy * dy + dz * dz - Radius * Radius
  509.  
  510.     ' Solve the quadratic A1*t^2 + B1*t + C1 = 0.
  511.     B24AC = b1 * b1 - 4 * A1 * C1
  512.     If B24AC < 0 Then
  513.         RayTraceable_FindT = -1
  514.         Exit Function
  515.     ElseIf B24AC = 0 Then
  516.         t1 = -b1 / 2 / A1
  517.     Else
  518.         B24AC = Sqr(B24AC)
  519.         t1 = (-b1 + B24AC) / 2 / A1
  520.         t2 = (-b1 - B24AC) / 2 / A1
  521.         ' Use only positive t values.
  522.         If t1 < 0.02 Then t1 = t2
  523.         If t2 < 0.02 Then t2 = t1
  524.         ' Use the smaller t value.
  525.         If t1 > t2 Then t1 = t2
  526.     End If
  527.  
  528.     ' If there is no positive t value, there's no
  529.     ' intersection in this direction.
  530.     If t1 < 0.02 Then
  531.         RayTraceable_FindT = -1
  532.         Exit Function
  533.     End If
  534.  
  535.     ' See where on the cylinder this point is.
  536.     HitU = t1 * A + B
  537.  
  538.     ' If this is not between Point1 and Point2,
  539.     ' ignore it.
  540.     If HitU < 0 Or HitU > 1 Then
  541.         RayTraceable_FindT = -1
  542.     Else
  543.         RayTraceable_FindT = t1
  544.     End If
  545. End Function
  546. ' Return the minimum and maximum distances from
  547. ' this point.
  548. Private Sub RayTraceable_GetRminRmax(new_min As Single, new_max As Single, ByVal X As Single, ByVal Y As Single, ByVal Z As Single)
  549. Dim dx As Single
  550. Dim dy As Single
  551. Dim dz As Single
  552. Dim dist As Single
  553.  
  554.     ' Find the distance to the first point.
  555.     dx = X - Point1.Trans(1)
  556.     dy = Y - Point1.Trans(2)
  557.     dz = Z - Point1.Trans(3)
  558.     dist = Sqr(dx * dx + dy * dy + dz * dz)
  559.     new_max = dist + Radius
  560.     new_min = dist - Radius
  561.  
  562.     ' Find the distance to the second point.
  563.     dx = X - Point2.Trans(1)
  564.     dy = Y - Point2.Trans(2)
  565.     dz = Z - Point2.Trans(3)
  566.     dist = Sqr(dx * dx + dy * dy + dz * dz)
  567.     If new_max < dist + Radius Then new_max = dist + Radius
  568.     If new_min > dist - Radius Then new_min = dist - Radius
  569.  
  570.     If new_min < 0 Then new_min = 0
  571. End Sub
  572. ' Reset the ForeverCulled flag.
  573. Private Sub RayTraceable_ResetCulling()
  574.     ForeverCulled = False
  575.     HadHitOnPreviousScanline = False
  576. End Sub
  577.  
  578.  
  579.